<template>
	<gui-page :customHeader="false">
		<template v-slot:gBody>
			<view class="container">

				<view class="game-info">
					<view class="game-section">
						<view class="" style="width:120rpx;text-align:center;">
							<text class="gui-text-small">在线：{{onLineUserCount}}人</text>
						</view>
						<view class="">
							<text>{{this.action=='own'?'主场':this.action=='join'?'客场':'观众'}}</text>
						</view>
						<view class="" style="width:120rpx;text-align:center;">
							<button type="default" style="display: inline;" class="gui-button gui-noborder"
								@tap="invitePlayer" hover-class="gui-tap" open-type="share">
								<text class="gui-icons gui-color-white gui-text"
									style="font-size: 32rpx;">&#xe606;</text>
							</button>
						</view>

					</view>
					<view class="game-header">
						<view class="game-title">
							局号：{{game_id}}
							<view class="gui-flex gui-justify-content-start gui-align-items-center">
								我方：
								<view class="white_chess" v-if="myHand=='white'">

								</view>
								<view class="black_chess" v-if="myHand=='black'">

								</view>
								<view class="" v-if="myHand=='-'">
									观众
								</view>
							</view>
						</view>
						<view class="game-vs">
							<view class="vs-avatar-img loader" v-if="mainUser">
								<image :src="mainUser.avatarUrl" mode="widthFix"
									style="width:80rpx;border-radius: 50%;z-index:-1;">
								</image>
								<view :class="myHand==gameHand?'pointer':''">

								</view>
							</view>
							<view class="vs-avatar-img loader" v-else>
								<view class="" style="width:80rpx;border-radius: 50%;">
									无
								</view>

							</view>
							VS
							<view class="vs-avatar-img loader" v-if="inviteUser">
								<image :src="inviteUser.avatarUrl" mode="widthFix"
									style="width:80rpx;border-radius: 50%;z-index:-1;">
								</image>
								<view :class="myHand!=gameHand?'pointer':''">

								</view>
							</view>
							<view class="" v-else style="width:80rpx;border-radius: 50%;">
								无
							</view>
						</view>

					</view>

					<view class="user-state">

						<view class="userinfo">
							<view v-for="(p,index) in onLineUsers" :key="index">
								<view class="user-container">
									<view class="icon-img icon-loader">
										<image :src="p.avatarUrl" mode="widthFix"
											style="width:80rpx;border-radius: 50%;z-index:-1;">
										</image>
									</view>
									<view class="player-name">
										{{p.nickName}}
									</view>
								</view>
							</view>

						</view>

						<view class="game-state gui-text-small">
							<view class="game-step">
								提示：{{stateTxt}}
							</view>
						</view>
					</view>


				</view>
				<view class="main" @click.prevent="stop">
					<image class="chessboard" src="../../static/bg/chessboard.png" mode="widthFix"></image>
					<view class="box" v-if="chessList" v-for="(chess,ind) in chessList" :key="ind">
						<hulu-chess @hold="location" :classname="chess.classname"
							:point="{x:chess.x,y:chess.y,classname:chess.classname,hand:chess.hand}"></hulu-chess>
					</view>
				</view>
				<gui-popup ref="guipopup" class="pop-modal" :canCloseByShade="false" bgColor="rgba(0, 0, 0, 0.5)">
					<view class="tip-txt">
						{{toast}}
					</view>
				</gui-popup>

				<gui-popup ref="guipopupWin" class="pop-modal" :canCloseByShade="false" bgColor="rgba(0, 0, 0, 0.5)">
					<view class="tip-txt">
						<image src="../../static/bg/win.png" mode="heightFix" class="chess-bg"></image>
						<button class="chess-btn" @click="toHail">确定</button>
					</view>
				</gui-popup>
				<gui-popup ref="guipopupLose" class="pop-modal" :canCloseByShade="false" bgColor="rgba(0, 0, 0, 0.5)">
					<view class="tip-txt">
						<image src="../../static/bg/lose.png" mode="heightFix" class="chess-bg"></image>
						<button class="chess-btn" @click="toHail">确定</button>
					</view>
				</gui-popup>
				<view class="chat-info gui-padding-x">
					<text class="gui-text-small">发送消息</text>
					<input id="msgRef" style="font-size: 28rpx;padding:4rpx 8rpx" v-model="sendTxt"
						placeholder="请输入内容" />
					<view @tap="openEmoji">
						<text class="gui-icons gui-block gui-color-orange gui-text"
							style="font-size: 48rpx;">&#xe66e;</text>
					</view>
					<button type="default" hover-class="gui-tap"
						class="gui-button-min gui-bg-blue1 gui-color-white chat-btn" @tap="sendChatMessage">发送</button>
				</view>
				<view class="system-notice">
					{{noticeMsg}}
				</view>
				<view class="chat-notice">
					<scroll-view scroll-y="true" style="height:140rpx;">
						<view class="chat-txt gui-text-small" v-for="(txt,ind) in chatMsgs" :key="ind">
							{{txt}}
						</view>
					</scroll-view>
				</view>
			</view>


			<gui-popup ref="bottomPopRef" position="bottom" width="380rpx">
				<view class="gui-relative gui-box-shadow gui-bg-white gui-dark-bg-level-1 demo-lr">
					<view class="gui-text-center gui-color-black gui-padding-small gui-text-small">
						表情符号
					</view>
					<text v-for="(e,index) in emojis" style="margin:10rpx;" @tap="tapEmoji(e)">
						{{e}}
					</text>
				</view>
				<view class="">
					<button type="default" hover-class="gui-tap" class="gui-button-min gui-bg-primary  gui-color-white"
						@tap="confirmEmoji">确定</button>
				</view>
				<view class="" style="height:60rpx;">

				</view>
			</gui-popup>


		</template>
	</gui-page>

</template>

<script>
	import Chess from './Chess.js'
	import Director from './Director.js'
	import request from '@/api/request.js'
	import graceJS from '@/Grace6/js/grace.js';
	import SocketCode from './enum.js'
	import {
		useUserStore
	} from '@/store/user.js'
	const useUser = useUserStore()
	import {
		useClientStore
	} from '@/store/client.js'
	import emojis from './emoji.js'
	// 客户端、用户
	const clientStore = useClientStore()
	export default {
		data() {
			return {
				emojis,
				sendTxt: "",
				chatMsgs: [],
				noticeMsg: '',
				chessList: [],
				director: null,
				game_id: null,
				area_id: useUser.getCurrentArea(),
				user: useUser.getUser(),
				stateTxt: "",
				myHand: "", //white|black|-
				parent_id: null,
				mainUser: null,
				inviteUser: null,
				game: {},
				gameHand: "",
				onLineUserCount: 0,
				onLineUsers: [],
				audio: null,
				toast: "", //弹窗提示信息
				action: null, //'join|own|look'加入|拥有者进入|围观
				pointer: "white", //开局时：myhand=='white'指示，进行时判断frontHand,我方与之相反
			}
		},
		onLoad(options) {
			this.game_id = options.game_id
			this.area_id = options.area_id
			this.action = options.action
			//缓存game_id 
			uni.setStorageSync("game_id", this.game_id)
		},
		async onShow() {
			console.log("battle onShow...")
			if (this.audio) {
				this.audio.play()
			} else {
				this.audio = uni.$hl.createHlAudio('stepping', true, false)
				this.audio.play()
			}
			//2、获取当前游戏
			await this.getGame()
			// 3、初始化双方棋手
			this.showHand()
			// 4、处理下棋逻辑
			this.handleLogic()
		},
		async onUnload() {
			if (this.audio) {
				this.audio.stop()
			}
			if (this.director) {
				this.director.close()
			}
			await request.post(`ws/close_client`, {
				userId: this.user.ID + "",
				systemId: this.area_id + "",
				gameId: this.game_id + "",
				clientId: uni.getStorageSync("client_id")
			})
		},
		async onHide() {
			if (this.audio) {
				this.audio.stop()
			}
			await request.post(`ws/close_client`, {
				systemId: this.area_id,
				clientId: uni.getStorageSync("client_id")
			})
			if (this.director) {
				this.director.close()
			}
		},
		onShareAppMessage(res) {
			if (res.from === 'button') { // 来自页面内分享按钮
				console.log(res.target)
			}
			return {
				title: '来一起围观吧',
				path: `/subpages/battle/battle?game_id=${this.game_id}&area_id=${this.area_id}&action=join`
			}
		},
		methods: {
			judgePlaysers() {
				let user_id = this.game.user_id
				let invite_id = this.game.invite_id
				let user_existed = this.onLineUsers.some(u => u.ID == user_id)
				let invite_existed = this.onLineUsers.some(u => u.ID == invite_id)
				// console.log("judgePlaysers user_existed invite_existed", user_id, invite_id, user_existed, invite_existed)
				return user_existed && invite_existed
			},
			async getGame() {
				const {
					data
				} = await request.get(`game/${this.game_id}`)
				this.game = data
				//判断上次下棋方的id，如果与当前user_id一样，则停止下棋
			},
			//处理下棋逻辑
			async handleLogic() {
				//如果客户手机突然返回桌面，需要提前清理一下this.chessList
				if (this.chessList.length > 0) {
					this.chessList = []
				}
				if (this.game.state == 0) {
					// 0:未开始
					this.initDirector(1)
					this.openModal(`等待玩家加入`)
					this.controlState(`等待玩家加入，请分享`)
					return
				}
				if (this.game.state == 1) {
					console.log("游戏状态：state=1->绑定玩家完成", )
					this.initDirector(1)
					return

				}
				if (this.game.state == 2) {
					let chess = this.game.Chesses[0]
					this.chessList = chess.ChessSteps.map(item => {
						return {
							classname: item.classname,
							hand: item.hand,
							chess_id: item.chess_id,
							x: item.x,
							y: item.y
						}
					})
					this.initDirector(2)
					return
				}
				if (state == 3) {
					console.log("结束")
				}
			},
			showHand() {
				if (this.action == 'look') {
					this.myHand = "-"
					this.controlState("游客状态，仅观察棋局")
				}
				if (this.user.ID == this.game.user_id) {
					this.myHand = this.game.user_hand
				}
				if (this.user.ID == this.game.invite_id) {
					this.myHand = this.game.invite_hand
				}
			},
			// 返回大厅
			toHail() {
				uni.navigateBack()
			},
			openModal(text) {
				this.toast = text
				// console.log(`[openModal：${text}]`)
				this.$refs.guipopup.open()
			},
			closeModal(text = "") {
				return new Promise((resolve, reject) => {
					// console.log("【closeModal】", text)
					this.toast = text
					this.$refs.guipopup.close()
					setTimeout(() => {
						resolve()
					}, 280)
				})
			},
			async getOnlineClient() {
				const {
					data
				} = await request.post("ws/get_online_list", {
					systemId: this.area_id,
					groupName: this.game_id,
					code: 2001,
					msg: "查询当前房间用户",
					data: "search user"
				})
				this.onLineUserCount = data.count;
				if (data.list) {
					this.onLineUsers = data.list.map(item => {
						const user = JSON.parse(item.extend)
						return user
					})
					let mainUserArr = this.onLineUsers.filter(item => item.ID == this.game.user_id)
					let inviteUserArr = this.onLineUsers.filter(item => item.ID == this.game.invite_id)
					if (mainUserArr.length > 0) {
						this.mainUser = mainUserArr[0]
					} else {
						this.mainUser = null
					}
					if (inviteUserArr.length > 0) {
						this.inviteUser = inviteUserArr[0]
					} else {
						this.inviteUser = null;
					}
				} else {
					console.error("++++++++--------")
				}
			},
			async location(pointObj) {
				console.log('点击的节点', pointObj, '我方棋色', this.myHand, '导演管理的chess', this.director.getHoldChess())
				//-1原则，如果不是空棋，或者我方棋子，报错
				if (!(pointObj.hand == this.myHand || pointObj.hand == 'empty')) {
					console.log("-1")
					uni.showToast({
						icon: "none",
						title: "无法操作"
					})
					return
				}
				//0、如果点击的是一个空棋子，什么也不做
				if (pointObj.hand == 'empty' && !this.director.getHoldChess()) {
					console.log("0")
					uni.showToast({
						icon: "none",
						title: "请先选择棋子"
					})
					return
				}

				//1、判断director中的holdChess是否有数据,无数据
				if (pointObj.hand == this.myHand) {
					//第二次点击的时候，是同一方棋子，交换
					console.log("1")
					if (this.director.getHoldChess()) {
						console.log("++++++有棋子++++++++")
						this.director.clearActiveStyle()

						let chessLst = this.director.setActiveStyle(pointObj)
						this.director.setHoldChess(pointObj)
					}
					if (!this.director.getHoldChess()) {
						console.log("++++++无棋子++++++++")
						let chessLst = this.director.setActiveStyle(pointObj)
						this.director.setHoldChess(pointObj)
					}
					//第一次触发时，没有active属性
					return
				}
				// 交换位置
				if (pointObj.hand == 'empty' && this.director.getHoldChess()) {
					console.log("2")
					let sourceChess = this.director.getHoldChess()
					let targetChess = pointObj
					const {
						action,
						data
					} = this.director.exchange(sourceChess, targetChess)

					if (action == "giveaway") {
						// 继续执行
						console.log("【让棋】继续执行")
						uni.showToast({
							icon: "none",
							title: "你需要让棋"
						})
						return
					}
					if (action == "done") {
						console.log("==================done")
						await request.post(`game/${this.game_id}/updateChess`, {
							client_id: uni.getStorageSync("client_id"),
							chess_list: data,
							hand: this.director.getHoldChess().hand,
							parent_id: this.parent_id,
						})
						return
					}
					if (action == 'gameover') {
						this.openModal("游戏结束")
						return
					}
				}
			},
			initDirector(state = 1) {
				if (!this.area_id) {
					uni.showToast({
						icon: 'error',
						title: "区域选择失败"
					})
					return
				}
				if (state == 1) {
					//开赛
					this.director = new Director(this.chessList, this.area_id, this.getWebsocketData, this
						.getWebsocketError,
						this.onErrorSucceed, this.successCallback)
					const {
						data,
						action
					} = this.director.initChess()
					this.chessList = data
					this.director.fillChessList(this.chessList)
					// console.log("state=1", this.director.chessList)
				}
				if (state == 2) {
					//进行中
					this.director = new Director(this.chessList, this.area_id, this.getWebsocketData, this
						.getWebsocketError,
						this.onErrorSucceed, this.successCallback)
					//不能出现ID，否则提交数据混乱
					this.director.fillChessList(this.chessList)
				}
			},
			//管理状态信息
			controlState(text) {
				this.stateTxt = text
			},
			async successCallback(hand) {
				if (hand == this.myHand) {
					//播放失败音频
					this.director.postVictoryVoice()
				} else {
					// 播放胜利音频
					this.director.postFailtureVoice()
				}
				await request.post(`game/${this.game.ID}/markSuccess`, {
					hand: hand,
					chess_list: this.chessList
				})
			},
			//玩家注册
			async register() {
				const {
					code
				} = await request.post("ws/register", {
					systemId: uni.getStorageSync("area_id")
				})
				if (code == 1) {
					// console.log("2、注册成功，首次注册systemId")
				}
				if (code == -1) {
					// console.log("2、注册成功，系统已经存在systemId：ajax")
				}
			},

			//绑定到当前游戏
			async bindGame() {
				await request.post("ws/bind_to_group", {
					systemId: uni.getStorageSync("area_id") + "",
					clientId: uni.getStorageSync("client_id"),
					groupName: this.game_id + "",
					userId: this.user.ID + "",
					extend: JSON.stringify(this.user)
				})
				// console.log("3、绑定房间Game：ajax")
			},
			async getWebsocketData(data) {
				let msgData = JSON.parse(data)
				console.log("socket coming...", msgData)
				switch (msgData.code) {
					case SocketCode.CHAT_TO_GAME_CODE:
						let msg = `【${msgData.msg}】${msgData.data}`
						this.chatMsgs.unshift(msg)
						break;
					case SocketCode.SYSTEM_NOTICE_CODE:
						this.noticeMsg = msgData.data
						setTimeout(() => {
							this.noticeMsg = ""
						}, 10000)
						break;
					case SocketCode.SUCCESS:
						const {
							clientId
						} = msgData.data
						uni.setStorageSync("client_id", msgData.data.clientId)
						// console.log("1、客户端连接成功，下发client_id成功,缓存client_id，尝试注册systemId")
						await this.register()
						await this.bindGame()
						await this.getOnlineClient()
						break;
					case SocketCode.BIND_GROUP_CODE:
						let sendUserId = msgData.sendUserId
						console.log('4、socket绑定游戏成功-userid:' + sendUserId)
						break;
					case SocketCode.ONLINE_MESSAGE_CODE:
						//不论是谁上线，都需要更新一下在线用户，同时清理一下上一次的遮罩层
						await this.getOnlineClient()
						//如果有人已经上线，获取一下game的状态，看看游戏是否处于玩家加入了
						await this.getGame()
						// console.log(this.game)
						const {
							data
						} = msgData;
						const dataObj = JSON.parse(data)
						const extendData = JSON.parse(dataObj.extend)
						this.controlState(`${extendData.nickName}已上线`)

						if (this.game.state == 0) {
							//更新一下房间用户
							this.controlState(`等待玩家加入...`)
							return
						}
						if (this.game.state == 1) {
							this.closeModal().then(_ => {
								if (this.judgePlaysers()) {
									this.controlState(`state=1双方已上线，游戏继续`)
									//如果是玩家绑定状态，这个时候需要白色方首先开局
									if (this.myHand != 'white') {
										setTimeout(() => {
											this.openModal(`对手开局，请等待`)
											this.gameHand = 'white'
										}, 280)

									}
								} else {
									setTimeout(() => {
										this.openModal("玩家不在线")
									}, 280)
								}
							})
							//开局的状况下
							return
						}
						if (this.game.state == 2) {
							//更新一下房间用户
							this.closeModal().then(_ => {
								if (this.judgePlaysers()) {
									this.controlState(`双方已上线，游戏继续`)
								} else {
									this.openModal("玩家不在线")
									return
								}
								let front_hand = this.game.Chesses[0]['hand']
								if (front_hand) {
									if (front_hand == this.myHand) {
										setTimeout(() => {
											this.openModal(`对手下棋，请稍后`)
											//交换gameHand
											this.gameHand = this.myHand == 'black' ? 'white' : 'black'
										}, 280)
									} else {
										setTimeout(() => {
											this.closeModal(`对手下棋，请稍后`).then(_ => {
												this.controlState(`我方下棋`)
												this.gameHand = this.myHand
											})
										}, 280)
									}
								}
							})
							return
						}

						break;
					case SocketCode.OFFLINE_MESSAGE_CODE:
						console.log("6、客户端下线");
						//更新一下房间用户
						await this.getOnlineClient()
						this.closeModal().then(_ => {
							setTimeout(async () => {
								if (this.game.state == 0) {
									return
								}
								if (this.game.state == 1) {
									//判断是否包含游戏玩家的双方，
									if (!this.judgePlaysers()) {
										setTimeout(() => {
											this.openModal("玩家离线")
										}, 280)
									}
									return
								}
								if (this.game.state == 2) {
									//判断是否包含游戏玩家的双方，
									if (!this.judgePlaysers()) {
										setTimeout(() => {
											this.openModal("玩家离线")
										}, 280)
									}
									return
								}

							}, 280)
						})

						break;
					case SocketCode.CHESS_STEP_CODE:
						console.log("5、棋子移动")
						//先让director的holdChess置空
						this.director.setHoldChess(null)
						if (this.game.state == 0) {
							return
						}
						console.log("5、socket下棋数据coming")
						const chessObj = JSON.parse(msgData.data)
						//在把parent_id设置为chessObj的ID
						this.parent_id = chessObj.ID
						const chess_steps = chessObj.chess_steps
						console.log(chess_steps)
						//注意：需要去除ID
						this.chessList = chess_steps.map(item => {
							return {
								classname: item.classname,
								hand: item.hand,
								chess_id: item.chess_id,
								x: item.x,
								y: item.y
							}
						})
						this.director.fillChessList(this.chessList)
						//更改下棋方
						let chess = chessObj.chess
						this.closeModal().then(_ => {
							setTimeout(() => {
								if (chess.user_id == this.user.ID) {
									this.openModal("对手下棋")
									this.controlState("对手下棋")
									this.gameHand = this.myHand == 'black' ? 'white' : 'black'
								} else {
									this.controlState("我方下棋")
									this.gameHand = this.myHand
								}
							}, 280)
						})
						return

						break;
					case SocketCode.DECLARE_SUCCESS:
						console.log("5、游戏结束")
						const winnerObj = JSON.parse(msgData.data)
						const c_steps = winnerObj.chess_list
						console.log("获胜方", winnerObj.hand)
						this.chessList = c_steps.map(item => {
							return {
								classname: item.classname,
								hand: item.hand,
								chess_id: item.chess_id,
								x: item.x,
								y: item.y
							}
						})
						this.director.fillChessList(this.chessList)
						if (winnerObj.hand == this.myHand) {
							this.$refs.guipopupWin.open()
						} else {
							this.$refs.guipopupLose.open()
						}
					default:
						break;
				}
			},
			getWebsocketError(err) {
				console.error("socket连接失败，删除当前玩家")
				//删除本地数据
				//从onLineUsers中讲mainUser删掉
				let index = this.onLineUsers.findIndex(item => item.ID == this.mainUser.ID)
				if (index != -1) {
					this.onLineUsers.splice(index, 1)
					this.mainUser = {}
				}
			},
			onErrorSucceed() {
				// console.error("onErrorSucceed")
			},
			openEmoji() {
				this.$refs.bottomPopRef.open()
			},
			confirmEmoji() {
				this.$refs.bottomPopRef.close()
			},
			tapEmoji(txt) {
				uni.createSelectorQuery().in(this) // 注意这里要加上 in(this)
					.select("#msgRef")
					.fields({
						properties: ["value"],
					})
					.exec((res) => {
						let newTxt = res[0].value += txt;
						this.sendTxt = newTxt
						console.log(this.sendTxt)
					})

			},
			// 发送聊天消息
			sendChatMessage() {
				request.post("ws/send_to_group", {
					sendUserId: JSON.parse(uni.getStorageSync("user"))["ID"] + "",
					groupName: this.game_id + "",
					code: 2013,
					msg: JSON.parse(uni.getStorageSync("user"))["nickName"] + "",
					data: this.sendTxt
				})
				this.sendTxt = ""
			},
		},
	}
</script>

<style lang="scss" scoped>
	@import "./battle.scss";

	.chat-btn {
		height: 60rpx;
		line-height: 60rpx;
		font-size: 32rpx;
	}

	.demo-close {
		width: 100rpx;
		height: 100rpx;
		line-height: 100rpx;
		opacity: 0.88;
		text-align: center;
		font-size: 58rpx;
	}

	.demo-lr {
		flex: 1;
		height: 400rpx;
	}

	.demo-lr-items {
		height: 400rpx;
		line-height: 120rpx;
		text-align: center;
		overflow: hidden;
	}

	.demo-msg {
		white-space: nowrap;
		line-height: 80rpx;
		font-size: 28rpx;
	}
</style>